using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Microsoft.DirectX;
using NovodexWrapper;

namespace OpenPanekitEditor.Panel
{
    public class PanelAttribute : System.Attribute
    {
        public string Name;
        public bool IsCore=false;
        public bool IsDeadEnd = false;
        public bool HasPivot=false;
        public bool HasActor= false;
        public string LocalD3DModelName;
        public string PivotD3DModelName;
        public string[] SlaveD3DModelNames;
        public PanelAttribute(string name){
            Name = name;
        }
    }
    public class PlayerControlSet
    {
        VirtualControler.Channels channel;
        public VirtualControler.Channels Channel
        {
            get { return channel; }
            set { this.channel = value; }
        }
        public float Value;
        public float LowerValue;
        public bool IsAnalog;
    }
    public class Parameter
    {
        public Parameter()
        {
            v = DefaultValue;
        }
        public virtual float UpperLimit
        {
            get { return 0; }
        }
        public virtual float LowerLomit
        {
            get { return 0; }
        }
        public virtual float Quantize
        {
            get { return 1; }
        }
        public virtual String Title
        {
            get { return "ParameterBase"; }
        }
        public virtual String Unit
        {
            get { return "N/A"; }
        }
        public virtual bool CanAssignControl
        {
            get { return false; }
        }
        public List<PlayerControlSet> PlayerControlList = new List<PlayerControlSet>();
        float v;
        public virtual float Value
        {
            get { return v; }
            set { v = value; }
        }
        float dv;
        public virtual float DefaultValue
        {
            get { return dv; }
            set { dv = value; }
        }
    }
    public class PanelUtil
    {
        public const float FoldUnit = (float)(Math.PI) / 12f;
        public const float PanelUnit = 1.0f;
        public const float F_PI = (float)Math.PI;
        public const float PanelDensity = 1.0f;
        public const float PanelMass = PanelDensity / 10f;
        public const float JointMass = PanelDensity / 20f;

        public static void RelatonPanel(IPanel dist, IPanel src, RelationDirection dir)
        {
            if (dist.ChildRelationDir.ContainsKey(dir))
            {
                return;
            }
            dist.ChildRelationDir[dir] = src;
            src.Parent = dist;
        }
        public static void PlayerControl(IPanel dist,VirtualControler input)
        {
            foreach (Parameter p in dist.ParameterDictionary.Values)
            {
                p.Value = p.DefaultValue;
                foreach (PlayerControlSet pc in p.PlayerControlList)
                {
                    if (pc.IsAnalog)
                    {
                        float d = pc.Value - pc.LowerValue;
                        p.Value = (input.GetChannelValue(pc.Channel) * d) + pc.LowerValue;
                    }
                    else
                    {
                        if (input.GetChannelState(pc.Channel))
                        {
                            p.Value = pc.Value;
                        }
                    }
                }
            }
        }
        public static void SerializeXML(IPanel panel,Schemas.Panel pxml)
        {
            if (panel.ParameterDictionary.Count <= 0)
                return;
            pxml.Parameter = new Schemas.PanelParameter[panel.ParameterDictionary.Count];
            int index = 0;
            foreach (Parameter p in panel.ParameterDictionary.Values)
            {
                Schemas.PanelParameter param_xml = new Schemas.PanelParameter();
                pxml.Parameter[index++] = param_xml;
                param_xml.ParameterName = String.Copy(p.GetType().FullName);
                param_xml.DefaultValue = p.DefaultValue;
                if (p.PlayerControlList.Count <= 0)
                    continue;
                param_xml.PlayerControl = new Schemas.PanelParameterPlayerControl[p.PlayerControlList.Count];
                int subindex = 0;
                foreach (PlayerControlSet pc in p.PlayerControlList)
                {
                    Schemas.PanelParameterPlayerControl pc_xml = new Schemas.PanelParameterPlayerControl();
                    param_xml.PlayerControl[subindex++] = pc_xml;
                    pc_xml.Channel = System.Enum.GetName(typeof(VirtualControler.Channels), pc.Channel);
                    pc_xml.Value = pc.Value;
                    pc_xml.LowerValue = pc.LowerValue;
                    pc_xml.IsAnalog = pc.IsAnalog;

                }
            }
        }
        public static void DeserializeXML(IPanel panel,Schemas.Panel pxml)
        {
            if (pxml.Parameter != null)
            {
                foreach (Schemas.PanelParameter p in pxml.Parameter)
                {
                    Type ptype = Document.GetTypeAllAssembly(p.ParameterName);
                    if (ptype == null)
                    {
                        throw new Exception();
                    }

                    Parameter param = panel.ParameterDictionary[ptype];
                    param.Value = p.DefaultValue;
                    if (param != null)
                    {
                        param.DefaultValue = p.DefaultValue;
                        if (p.PlayerControl == null)
                            continue;
                        foreach (Schemas.PanelParameterPlayerControl pc in p.PlayerControl)
                        {
                            PlayerControlSet pset = new PlayerControlSet();
                            pset.Channel = (VirtualControler.Channels)Enum.Parse(typeof(VirtualControler.Channels), pc.Channel);
                            pset.Value = pc.Value;
                            pset.LowerValue = pc.LowerValue;
                            pset.IsAnalog = pc.IsAnalog;
                            param.PlayerControlList.Add(pset);
                        }
                    }
                }
            }
        }
    }
    public enum RelationDirection
    {
        X_NEGATIVE, X_POSITIVE, Z_NEGATIVE, Z_POSITIVE,CENTOR
    }
    public class NxActorExtend 
    {
        public NxActor Actor;
        public List<Vector3> VertexCloud = new List<Vector3>();
        public void CreateShape()
        {
            Actor.createShape(NovodexUtil.createConvexShapeDescFromVertexCloud(VertexCloud.ToArray()));
            
        }
    }
    public interface IPanel
    {
        Image IconImage { get; }

        NxActor InitNx(NxScene scene,NxActor parent,Matrix pmatrix);
        void UpdateNxParameter(float dt);
        NxActor GetSlaveNxActor(NxScene scene);
        NxActor LocalNxActor { get; }
        
        Dictionary<Type, Parameter> ParameterDictionary { get; }
        int FoldingAngle { get;set; }
        Dictionary<RelationDirection, IPanel> ChildRelationDir{get;}
        IPanel Parent { get;set; }

        Matrix LocalToRootMatrix { get; set; }
        Matrix PivotToRootMatrix { get; set; }

        Matrix PivotMatrix { get; set;}
    
    }

}
